package com.emotion.recognition.server.mlp;

import java.util.List;
import java.util.Random;

import com.emotion.recognition.shared.Emotion;
import com.google.gwt.rpc.server.Pair;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
import com.google.gwt.thirdparty.guava.common.collect.Lists;

/**
 * For testing MLP neural network.
 * 
 * @author Minsang
 */
public class MlpTest {

    public static void main(String[] args) {

        MLP net = MLP.builder().setInputLayer(4, 1.0d).addHiddenLayer(4, 1.0d).setOutputLayer(4)
                .setMaxEpochs(1000).setDesiredMaxError(0.1).buildClassifier();

        // try a set of input values

        Pair<List<List<Double>>, List<List<Double>>> data = createSampleData();

        double mse = net.train(data.getA(), data.getB());
        System.out.println("MSE : " + mse);

        // ASTONISHED("0001"), CALM("0010"), SAD("0100"), SMILING("1000"), NONE("0000");
        System.out.println("ASTON CALM  SAD   SMILE");
        filter(net.sim(Lists.newArrayList(0.9d, 0.5d, 0.5d, 0.5d))); // 0001
        filter(net.sim(Lists.newArrayList(0.63d, 0.5d, 0.5d, 0.5d))); // 0010
        filter(net.sim(Lists.newArrayList(0.4d, 0.5d, 0.5d, 0.5d))); // 0100
        filter(net.sim(Lists.newArrayList(0.1d, 0.5d, 0.5d, 0.5d))); // 1000

        net.debugPrint();
    }

    private static void filter(List<Double> inputs) {
        for (double d : inputs) {
            System.out.printf("%.3f ", d);
        }
        System.out.println();
    }

    private static Pair<List<List<Double>>, List<List<Double>>> createSampleData() {
        List<List<Double>> inputs = Lists.newArrayList();
        List<List<Double>> targets = Lists.newArrayList();

        Random r = new Random(1234L);

        for (int i = 0; i < 100; i++) {
            double d1 = r.nextDouble();
            double d2 = r.nextDouble();
            double d3 = r.nextDouble();
            double d4 = r.nextDouble();

            Emotion target;

            if (d1 > 0.75) {
                target = Emotion.ASTONISHED; // 0001
            } else if (d1 > 0.50) {
                target = Emotion.CALM; // 0010
            } else if (d1 > 0.25) {
                target = Emotion.SAD; // 0100
            } else {
                target = Emotion.SMILING; // 1000
            }

            if (target != Emotion.NONE) {
                inputs.add(ImmutableList.of(d1, d2, d3, d4));
                targets.add(target.getOneHotEncoded());

                // System.out.println(String.format("%f %f %f %f = %s %s", d1, d2, d3, d4,
                // target.toString(), target.getOneHotEncoded().toString()));

            }
        }

        return new Pair<List<List<Double>>, List<List<Double>>>(inputs, targets);
    }
}
